package motionsApp.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

import motionsApp.client.MotionsService;
import motionsApp.shared.MotionDTO;

import com.google.appengine.api.datastore.Key;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class MotionsServiceImpl extends RemoteServiceServlet implements
		MotionsService {
	
	private PersistenceManagerFactory persistancefactory;
	
	public MotionsServiceImpl()
	{
		persistancefactory = JDOHelper.getPersistenceManagerFactory("transactions-optional");
	}	

	public String addNewMotion(List<MotionDTO> motions) throws IllegalArgumentException {
		// Verify that the input is valid. 

		PersistenceManager persistenceManager = persistancefactory.getPersistenceManager();
		for (MotionDTO motion : motions) {
			String escapedMotion = escapeHtml(motion.getName());
			persistenceManager.makePersistent(new Motion(escapedMotion));
		}
		
		persistenceManager.close();
        
        if(motions.size() == 1)
        {
        	return "Motion: '" + motions.get(0).getName() + "' added";
        }
        
        return "Added " + motions.size() + " motions";  
	}
	
	private String escapeHtml(String html) {
		if (html == null) {
			return null;
		}
		return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
				.replaceAll(">", "&gt;");
	}

	@Override
	public List<MotionDTO> getMotions() {
		List<MotionDTO> motions = new ArrayList<MotionDTO>();		
		
		PersistenceManager persistenceManager = persistancefactory.getPersistenceManager();
		@SuppressWarnings("unchecked")
		List<Motion> dbMotions = (List<Motion>) persistenceManager.newQuery(Motion.class).execute();
		List<Label> dbLabels = (List<Label>) persistenceManager.newQuery(Label.class).execute();
		persistenceManager.close();
		HashMap<Key, Label> labelsMap = new HashMap<Key, Label>();
		for (Label label : dbLabels) {
			labelsMap.put(label.getKey(), label);
		}
		for (Motion entity : dbMotions) {
			ArrayList<String> labels = new ArrayList<String>();
			for (Key label : entity.getLabels()) {
				labels.add(labelsMap.get(label).getName());
			}
			motions.add(new MotionDTO(entity.getName(), labels));
		}
		
		return motions;
	}

	@Override
	public MotionDTO getRandomMotion() {
		PersistenceManager persistenceManager = persistancefactory.getPersistenceManager();
		@SuppressWarnings("unchecked")
		List<Motion> dbMotions = (List<Motion>) persistenceManager.newQuery(Motion.class).execute();
		persistenceManager.close();
		
		int motionIndex = new Random().nextInt(dbMotions.size());		
		return new MotionDTO(dbMotions.get(motionIndex).getName(), new ArrayList<String>());
	}

	@Override
	public void updateMotion(MotionDTO motion) {
		PersistenceManager persistenceManager = persistancefactory.getPersistenceManager();
		@SuppressWarnings("unchecked")
		List<Motion> dbMotions = (List<Motion>) persistenceManager.newQuery(Motion.class, "name == '" + motion.getName() + "'").execute();
		
		List<Label> newLabels = new ArrayList<Label>(); 
		
		for (String labelText : motion.getLabels()) {
			@SuppressWarnings("unchecked")
			List<Label> labels = (List<Label>)persistenceManager.newQuery(Label.class, "name == '" + labelText +"'").execute();
			if(labels.size() > 0) {
				newLabels.add(labels.get(0));
			}
			else {
				Label label = new Label(labelText);
				persistenceManager.makePersistent(label);
				newLabels.add(label);
			}
		}
		
		List<Key> labelKeys = new ArrayList<Key>();
		for (Label label : newLabels) {
			labelKeys.add(label.getKey());
		}
		
		dbMotions.get(0).setLabels(labelKeys);
		
		
		persistenceManager.close();	
	}	
}
